//----------------------------------------------------------
// File.h
//   File utility, classes for basic input/output
//      filestream activities
// Loosely based off code from DeVry University, GSP420
//----------------------------------------------------------

#ifndef _FILE_H_
#define _FILE_H_

#include <fstream>
#include <stdarg.h>

// File Related Defines
enum E_FILE_TYPE { 
	E_TEXT_FILE = 1, 
	E_BINARY_FILE 
};

// Abstract class to inherit from
class FileStream
{
public:

	// constructor/destructor
	FileStream() : m_fileSize(0) {}
	virtual ~FileStream() {}

	virtual bool OpenFile(const char *fileName, E_FILE_TYPE fileType) = 0;
	virtual void CloseFile() = 0;

	virtual void SeekStreamToStart() = 0;
	virtual void SeekStreamToEnd() = 0;
	virtual void SeekPast(int offset) = 0;
	virtual int GetSeekPosition() = 0;

	virtual bool Read(char *buffer, int bytesToRead) = 0;
	virtual bool Write(char *buffer, int bytesToWrite) = 0;

	int GetFileSize() { return m_fileSize; }
	virtual bool isOpen() = 0;

protected:
	int m_fileSize;
};

// Inherited input class
class FileInputStream : public FileStream
{
public:

	// constructor/destructor
	FileInputStream() {}
	
	FileInputStream(const char *fileName, E_FILE_TYPE fileType)
	{
		OpenFile(fileName, fileType);
	}

	~FileInputStream()
	{
		CloseFile();
	}

	bool OpenFile(const char *fileName, E_FILE_TYPE fileType);
	void CloseFile();

	void SeekStreamToStart();
	void SeekStreamToEnd();
	void SeekPast(int offset);
	int GetSeekPosition();

	bool Read(char *buffer, int bytesToRead);
	bool Write(char *buffer, int bytesToWrite);
	  
	bool isOpen();

private:
	std::ifstream m_fileStream;
};

// Inherited output class
class FileOutputStream : public FileStream
{
public:
	FileOutputStream() {}

	FileOutputStream(const char *fileName, E_FILE_TYPE fileType)
	{
		OpenFile(fileName, fileType, false);
	}

	FileOutputStream(const char *fileName, E_FILE_TYPE fileType, bool truncate = false)
	{
		OpenFile(fileName, fileType, truncate);
	}

	~FileOutputStream()
	{
		CloseFile();
	}
	  
	bool OpenFile(const char *fileName, E_FILE_TYPE fileType, bool truncate);

	bool OpenFile(const char *fileName, E_FILE_TYPE fileType) 
	{
		return OpenFile(fileName, fileType, false);
	}

	void CloseFile();

	void SeekStreamToStart();
	void SeekStreamToEnd();
	void SeekPast(int offset);
	int GetSeekPosition();

	bool Read(char *buffer, int bytesToRead);
	bool Write(char *buffer, int bytesToWrite);

	bool isOpen();

private:
	std::ofstream m_fileStream;
};

#endif